package com.by.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;

@Component
public class JwtUtil {

    /**
     * JWT 签名密钥（从配置文件注入）
     * 要求至少 32 个字符，才能满足 HS256 的安全性要求
     */
    @Value("${jwt.secret}")
    private String secret;

    /** Access Token 过期时间（毫秒） */
    @Value("${jwt.access.expiration}")
    private long accessExpiration;

    /** Refresh Token 过期时间（毫秒） */
    @Value("${jwt.refresh.expiration}")
    private long refreshExpiration;

    /**
     * 把字符串 secret 转换成 SecretKey
     * 使用 Keys.hmacShaKeyFor() 来保证 key 长度和算法匹配
     */
    private SecretKey getSigningKey() {
        return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 生成 Access Token
     * @param userName 用户名（或用户ID）
     * @return JWT 字符串
     */
    public String generateAccessToken(String userName) {
        return Jwts.builder()
                .setSubject(userName) // 设置主体（sub），通常是用户唯一标识
                .setIssuedAt(new Date()) // 签发时间（iat）
                .setExpiration(new Date(System.currentTimeMillis() + accessExpiration)) // 过期时间（exp）
                .signWith(getSigningKey(), SignatureAlgorithm.HS256) // 使用 HS256 算法 + 安全 key 签名
                .compact(); // 生成最终的 Token 字符串
    }

    /**
     * 生成 Refresh Token
     * @param userName 用户名（或用户ID）
     * @return JWT 字符串
     */
    public String generateRefreshToken(String userName) {
        return Jwts.builder()
                .setSubject(userName)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + refreshExpiration))
                .signWith(getSigningKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    /**
     * 校验 Token 是否有效（签名 + 过期时间）
     * @param token JWT 字符串
     * @return true 表示合法，false 表示非法或过期
     */
    public boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(getSigningKey()) // 设置签名密钥
                    .build()
                    .parseClaimsJws(token); // 校验签名 + 解析 Payload
            return true;
        } catch (JwtException e) {
            // 捕获所有 JWT 异常（过期、格式错误、签名无效等）
            return false;
        }
    }

    /**
     * 从 Token 中获取用户名（即 Subject）
     * @param token JWT 字符串
     * @return 用户名
     */
    public String getUsernameFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject(); // 获取 "sub" 字段
    }

    /**
     * 获取 Token 剩余有效期（毫秒）
     * @param token JWT 字符串
     * @return 剩余时间（<=0 表示过期）
     */
    public long getExpiration(String token) {
        try {
            Date expiration = Jwts.parserBuilder()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody()
                    .getExpiration(); // 获取 exp 字段
            return expiration.getTime() - System.currentTimeMillis();
        } catch (Exception e) {
            return -1; // 如果解析失败，返回 -1
        }
    }
}
